﻿/*****************************************************************************
 
 Use of Ext is under the Ext JS license, for more information, 
 please visit http://extjs.com/products/license.php page. 
  
 You should confirm that you have read, understood and accept ethical criteria listed. 
 If not, see <http://www.mvcnext.com/license/>.
  
 Version: 1.0.0.0
 Website: http://www.mvcnext.com/
 
 Copyright (c) Yoganand R. All rights reserved.
 For continued development and updates, visit http://yogsbreath.net
 
 ******************************************************************************/
using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Web.UI;
using System.Text;

namespace MVCnExt.Web.UI.Ext
{
    [ToolboxData("<{0}:ExtStore />")]
    public class ExtStore : Store
    {
        private List<ScriptReference> _references = new List<ScriptReference>();

        private List<SortInfo> _sortInfo = new List<SortInfo>();

        public override IList<ScriptDescriptor> GetScriptDescriptors()
        {
            IList<ScriptDescriptor> list = base.GetScriptDescriptors();

            if (list.Count == 0)
                list.Add(new ExtScriptControlDescriptor("Ext.data.Store", "ctl00"));

            ScriptControlDescriptorBase desc = (ScriptControlDescriptorBase)list[0];

            desc.Type = "Ext.data.Store";

            String[] properties = new String[]{
                "pruneModifiedRecords", "remoteSort", "warningOnDirty", "dirtyWarningTitle", 
                "groupField", "groupOnSort", "remoteGroup", "ignoreExtraFields", "url"
            };

            Type component = typeof(ExtStore);

            foreach (String property in properties)
            {
                PropertyInfo i = component.GetProperty(property);

                if (i == null)
                    throw new InvalidOperationException(String.Format("Property not found, 'ExtStore.{0}'", property));

                Object value = i.GetValue(this, null);

                if (value == null)
                {
                    continue;
                }

                if (!(value is String))
                    desc.AddPropertyBase(property, value);
                else
                    desc.AddPropertyBase(property, String.Format("'{0}'", value));
            }
            //add items
            if (proxy != null && proxy.Count != 0)
            {
                // build items list
                StringBuilder tabList = new StringBuilder("");

                for (int i = 0; i < proxy.Count; i++)
                {
                    // add comma between items
                    if (i != 0)
                    {
                        tabList.Append(",");
#if DEBUG
                        tabList.AppendLine("\t\t\t");
#endif
                    }

                    // get the item script
                    IList<ScriptDescriptor> descriptors = proxy[i].GetScriptDescriptors();

                    // write the item's config to the list
                    tabList.Append(((ExtScriptControlDescriptor)descriptors[0]).WriteScript(ScriptType.NewOnly));
                }

                tabList.Append("");

                desc.AddPropertyBase("proxy", tabList);
            }

            //add reader
            if (reader.Count != 0)
            {
                // build items list
                StringBuilder tabList = new StringBuilder("");

                for (int i = 0; i < reader.Count; i++)
                {
                    // add comma between items
                    if (i != 0)
                    {
                        tabList.Append(",");
#if DEBUG
                        tabList.AppendLine("\t\t\t");
#endif
                    }

                    // get the item script
                    IList<ScriptDescriptor> descriptors = reader[i].GetScriptDescriptors();

                    // write the item's config to the list
                    tabList.Append(((ExtScriptControlDescriptor)descriptors[0]).WriteScript(ScriptType.NewOnly));
                }

                tabList.Append("");

                desc.AddPropertyBase("reader", tabList);
            }

            //add sortInfo
            if (sortInfo != null)
            {
                StringBuilder config = new StringBuilder("{");

                config.AppendFormat("field: '{0}', direction: '{1}'", sortInfo.field, sortInfo.direction);

                config.Append("}");

                desc.AddPropertyBase("sortInfo", config);
            }

            //add selection model
            if (data != null && !string.IsNullOrEmpty(data.Description.ToString()))
            {
                desc.AddPropertyBase("data", data.Description.ToString().Trim().Replace(Environment.NewLine, ""));
            }
          

            return list;
        }

        #region Public Properties

        /// <summary>
        /// An array of field definition objects, or field name strings.
        /// </summary>                      
        [Description("An array of field definition objects, or field name strings.")]
        [Bindable(true)]
        [DefaultValue("")]
        [Localizable(true)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ExtData data { get; set; }

        ///// <summary>   
        ///// The Proxy object which provides access to a data object.
        ///// </summary>
        //[NotifyParentProperty(true)]
        //[PersistenceMode(PersistenceMode.InnerProperty)]
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        //[Description("The Proxy object which provides access to a data object.")]
        //public List<ExtProxy> proxy { get; set; }


        ///// <summary>
        ///// The DataReader object which processes the data object and returns an Array of Ext.data.Record objects which are cached keyed by their id property.
        ///// </summary>
        //[Description("The ExtReader object which processes the data object and returns an Array of Ext.data.Record objects which are cached keyed by their id property.")]
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        //[PersistenceMode(PersistenceMode.InnerProperty)]
        //[TemplateContainer(typeof(ExtContainer))]
        //[TemplateInstance(TemplateInstance.Single)]
        //public List<ExtReader> reader { get; set; }

        ///// <summary>
        ///// An object which determines the Store sorting information.
        ///// </summary>
        //[NotifyParentProperty(true)]
        //[PersistenceMode(PersistenceMode.InnerProperty)]
        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        //[Description("An object which determines the Store sorting information.")]
        //public SortInfo sortInfo { get; set; }

        /// <summary>
        /// The default URL to be used for requests to the server.
        /// </summary>        
        [Description("The default URL to be used for requests to the server.")]
        public String url { get; set; }
             

        ///// <summary>
        ///// True if sorting is to be handled by requesting the Proxy to provide a refreshed version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false). If remote sorting is specified, then clicking on a column header causes the current page to be requested from the server with the addition of the following two parameters: sort: String - The name (as specified in the Record's Field definition) of the field to sort on. dir : String - The direction of the sort, 'ASC' or 'DESC' (case-sensitive).
        ///// </summary>
        //[Description("True if sorting is to be handled by requesting the Proxy to provide a refreshed version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false). If remote sorting is specified, then clicking on a column header causes the current page to be requested from the server with the addition of the following two parameters: sort: String - The name (as specified in the Record's Field definition) of the field to sort on. dir : String - The direction of the sort, 'ASC' or 'DESC' (case-sensitive).")]
        //public Boolean? remoteSort { get; set; }

        /// <summary>
        /// If true show a warning before load/reload if store has dirty data
        /// </summary>
        [DefaultValue(true)]
        [Description("If true show a warning before load/reload if store has dirty data")]
        public Boolean warningOnDirty { get; set; }

        /// <summary>
        /// The title of window showing before load if the dirty data exists
        /// </summary>
        [DefaultValue("Uncommitted Changes")]
        [Description("The title of window showing before load if the dirty data exists")]
        public String dirtyWarningTitle { get; set; }

        /// <summary>
        /// The text of window showing before load if the dirty data exists
        /// </summary>
        [DefaultValue("You have uncommitted changes.  Are you sure you want to load/reload data?")]
        [Description("The text of window showing before load if the dirty data exists")]
        public String dirtyWarningText { get; set; }

        public Boolean? useIdConfirmation { get; set; }

        /// <summary>
        /// The field name by which to sort the store's data (defaults to '').
        /// </summary>
        [DefaultValue("")]
        [Description("The field name by which to sort the store's data (defaults to '').")]
        public String groupField { get; set; }

        /// <summary>
        /// True to sort the data on the grouping field when a grouping operation occurs, false to sort based on the existing sort info (defaults to false).
        /// </summary>
        [Description("True to sort the data on the grouping field when a grouping operation occurs, false to sort based on the existing sort info (defaults to false).")]
        public Boolean? groupOnSort { get; set; }

        /// <summary>
        /// True if the grouping should apply on the server side, false if it is local only (defaults to false). If the grouping is local, it can be applied immediately to the data. If it is remote, then it will simply act as a helper, automatically sending the grouping field name as the 'groupBy' param with each XHR call.
        /// </summary>
        [Description("True if the grouping should apply on the server side, false if it is local only (defaults to false). If the grouping is local, it can be applied immediately to the data. If it is remote, then it will simply act as a helper, automatically sending the grouping field name as the 'groupBy' param with each XHR call.")]
        public Boolean? remoteGroup { get; set; }

        /// <summary>
        /// If true then only properties included to reader will be converted to json
        /// </summary>
        [DefaultValue(true)]
        [Description("If true then only properties included to reader will be converted to json")]
        public Boolean ignoreExtraFields { get; set; }

        #endregion
    }
}
